/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.edit.policy;

import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.Request;
import org.eclipse.gef.commands.Command;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.gef.editpolicies.XYLayoutEditPolicy;
import org.eclipse.gef.requests.CreateRequest;
import org.eclipse.uml2.uml.UMLPackage;

import com.cea.papyrus.diagram.sequence.sedi.edit.CFEditPart;
import com.cea.papyrus.diagram.sequence.sedi.edit.FrameEditPart;
import com.cea.papyrus.diagram.sequence.sedi.edit.handlers.CombinedFragmentCreateHandler;
import com.cea.papyrus.diagram.sequence.sedi.edit.handlers.CombinedFragmentLayoutHandler;
import com.cea.papyrus.diagram.sequence.sedi.edit.handlers.InteractionAddCFHandler;
import com.cea.papyrus.diagram.sequence.sedi.edit.handlers.InteractionCreationHandler;
import com.cea.papyrus.diagram.sequence.sedi.edit.handlers.InteractionLayoutHandler;
import com.cea.papyrus.diagram.sequence.sedi.model.command.diagram.SetBoundsHintCommand;

/**
 * Layout policy that is installed on Diagram edit parts.
 * 
 * @todo There is a lot of common code shared between DiagramLayoutPolicy
 *       and FrameLayoutPolicy. Examine ways to refactor. 
 *
 * @author Andreas Limyr
 * @author frankd@ifi.uio.no
 */
public class DiagramLayoutPolicy extends XYLayoutEditPolicy {

	@Override
	protected Command createAddCommand(EditPart child, Object constraint) {
		// FIXME THIS CODE IS NEVER USED (I think)
		Command[] cmds = null;
		if (child instanceof CFEditPart) {
			cmds = new InteractionAddCFHandler(this).
				getAddCommands((GraphicalEditPart)child, (Rectangle)constraint);
		}
		
		if (cmds != null) {
			CompoundCommand ccmd = new CompoundCommand();
			for (Command c : cmds)
				ccmd.add(c);
			return ccmd;
		}
		return null;		
	}

	@Override
	protected Command createChangeConstraintCommand(
			EditPart childEP, Object constraint) {
		
		CompoundCommand ccmd = new CompoundCommand();
		
		Command[] cmds = null;
		if (childEP instanceof FrameEditPart) {
			cmds = new InteractionLayoutHandler().getMoveCommands(childEP, (Rectangle) constraint);
			ccmd.setLabel("Move/resize Interaction");
		}
		else if (childEP instanceof CFEditPart) {
			cmds = new CombinedFragmentLayoutHandler().getMoveCommands(childEP, (Rectangle) constraint);
			ccmd.setLabel("Move/resize CombinedFragment");
		}

		if (cmds != null) {
			for (Command c : cmds)
				ccmd.add(c);
			return ccmd;
		}
		return null;
	}

	@Override
	protected Command getCreateCommand(CreateRequest request) {
		EClass umlClass = (EClass) request.getNewObject();
		
		final CompoundCommand ccmd = new CompoundCommand();
		ccmd.setLabel("Create");
		
		// All children have bounds
		final Rectangle constraint = (Rectangle) getConstraintFor(request);
		final Rectangle bounds = new Rectangle(constraint.x, constraint.y, 0, 0);
		SetBoundsHintCommand hintCmd = new SetBoundsHintCommand();
		hintCmd.setHint(bounds);
		ccmd.add(hintCmd);

		// Delegate the rest of the creation process to the creation handlers
		Command[] cmds = null; 
		if (umlClass == UMLPackage.eINSTANCE.getInteraction())
			cmds = new InteractionCreationHandler(this).getCreateCommands(request);
		else if (umlClass == UMLPackage.eINSTANCE.getCombinedFragment())
			cmds = new CombinedFragmentCreateHandler(this).getCreateCommands(request, constraint.getLocation());

		if (cmds != null) {
			for (Command cmd : cmds)
				ccmd.add(cmd);
			return ccmd;
		}
		return null;
	}

	// The LayoutEditPolicy implementation always installs a PRIMARY_DRAG_ROLE
	// edit policy on children, overriding any that is already installed.
	// We actually really want to keep the one we have installed on the editpart,
	// because resizing and movement policies differs for some editparts.
	// EOs, for example, can only resize downwards, and several editparts
	// snap to other objects in different ways.
	@Override
	protected void decorateChild(EditPart child) {
		if (child.getEditPolicy(EditPolicy.PRIMARY_DRAG_ROLE) == null)
			super.decorateChild(child);
	}

	/*
	protected EditPolicy createChildEditPolicy(EditPart child) {
		return new ResizableEditPolicy();
	} */
	
	@Override
	protected Command getDeleteDependantCommand(Request arg0) {
		return null;
	}
}
